# CallWordSend.py
####################################################################################
##    This script calls usfm2word.exe of the WordSend project to convert the USFM  #
##    files of the current Paratext project to Microsoft Word 2003 (or later) XML. #
##    The job options file and default output file will be placed in the WordSend  #
##    folder under the selected Paratext project folder.                           #
##                                                                                 #
##    This script is to be called from Paratext 6 or later, and depends on         #
##    ScriptureObjects.py.                                                         #
##                                                                                 #
##    CallWordSend.py and CallWordSend.cms are copyright (c) 2006 SIL, Evangel     #
##    Bible Translators, and Rainbow Missions, Inc. and released under the Gnu     #
##    Lesser Public License or Common Public License, as explained in the file     #
##    LICENSING.txt in the WordSend installation directory.                        #
####################################################################################
# Author: Michael Paul Johnson <Michael_Paul_Johnson@sil.org>
# Web site: http://eBible.org/wordsend/
##  4 Oct 2006 - Initial version

import re
import ScriptureObjects
import os
import os.path
import sys
# I wish I could import xml.parsers.xpat, but Paratext's Python distribution doesn't have it.

def parseXiniString(s, newXini):    # Not a full-blown XML parser; just enough to deal with an xini file.
    i = 0                 # i indicates the position within the string where we are parsing.
    elementPattern = re.compile("<[a-zA-Z0-9_ ]*?>")        # Matches an XML start element <name>
    endElementPattern = re.compile("</[a-zA-Z0-9_ ]*?>")    # Matches an XML end element </name>
    emptyElementPattern = re.compile("<[a-zA-Z0-9_ ]*?/>")  # Matches an XML empty element <name />
    miscElementPattern = re.compile(r"<[\?\!].*?>")         # Matches an XML declaration or comment
    textPattern = re.compile(r"[^<]+")                      # Matches text between XML tags
    namePattern = re.compile("[a-zA-Z_0-9]*")               # Matches the name (not attributes) of an XML element
    currentElementName = ""                                 # The current leaf element name (key or value)
    currentKey = ""                                         # The current key name
    currentValue = ""                                       # The current value name
    while i < len(s):                                       # Iterate through the entire string
        mo = emptyElementPattern.match(s, i)
        if mo:  # If this is an empty element
            nameMo = namePattern.match(s, i + 1)
            if nameMo:
                currentElementName = nameMo.group()
                if currentElementName == "value":
                    currentValue = ""
                elif currentElementName == "key":
                    currentKey = ""
                currentElementName = "" # Empty element ends here; don't add more text
            i = mo.end() # Resume parsing after this element.
        else:            
            mo = elementPattern.match(s, i)
            if mo:  # If this is a start element
                nameMo = namePattern.match(s, i + 1)
                if nameMo:
                    currentElementName = nameMo.group()
                i = mo.end()
                # print("Element "+currentElementName)
            else:
                mo = endElementPattern.match(s, i)
                if mo:  # If this is an end element
                    nameMo = namePattern.match(s, i + 2)
                    if nameMo:
                        name = nameMo.group()
                        if (name == "entry"): # Copy keys we won't get from Paratext to the output unchanged.
                            if (currentKey != "") and not (re.compile("^sfmFile").match(currentKey)) and (currentKey != "fromParatext") and (currentKey != "numSfmFiles") and (currentKey != "outputFileName"):
                                newXini = newXini + "<entry>\n  <key>" + currentKey + "</key>\n  <value>" + currentValue + "</value>\n</entry>\n"
                        currentElementName = "" # not in key or value
                        i = mo.end()
                        # print("End element "+name)
                else:
                    mo = miscElementPattern.match(s, i)
                    if mo:  # If this is a misc. element like document type declaration or comment, skip it. (We already have what we need.)
                        i = mo.end()
                        # print("Misc element")
                    else:
                        mo = textPattern.match(s, i)
                        if mo:  # If this is text
                            text = mo.group()
                            if currentElementName == "key":
                                currentKey = text
                                # print("currentKey='"+currentKey+"'")
                            elif currentElementName == "value":
                                currentValue = text
                                # print("currentValue='"+currentValue+"'")
                            i = mo.end()
                        else:
                            i = i + 1
    return newXini    # lest our changes be lost...

def updateXini(fileName):
    newXini = '<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE ini SYSTEM "ini.dtd">\n<ini>\n' # Declaration and root element
    try:
        # print("Reading " + fileName)
        if os.path.exists(fileName):
            infile = open(fileName)         # Open the xini file
            xini = infile.read()            # ...and read it into <xini>
            infile.close()                  # ...then close the file
            # print("Read " + fileName + ", parsing...")
            newXini = parseXiniString(xini, newXini)
    except OSError:
        print(fileName + " not found, creating...")
    try:
        # print("Writing " + fileName)
        outfile = open(fileName, 'w')
        outfile.write(newXini) # Document declaration plus any existing parameters
        # Get the file list from Paratext
        numSfmFiles = 0
        for threePartFileInfo in myFiles:
            outfile.write("<entry>\n  <key>sfmFile" + repr(numSfmFiles) + "</key>\n  <value>" + threePartFileInfo[0] + "</value>\n</entry>\n")
            numSfmFiles = numSfmFiles + 1
        outfile.write("<entry>\n  <key>numSfmFiles</key>\n  <value>" + repr(numSfmFiles) + "</value>\n</entry>\n")
        # Put the default output file in the WordSend directory under the Paratext project directory
        outfile.write("<entry>\n  <key>outputFileName</key>\n  <value>" + selectedProject.directory + "\\WordSend\\" + selectedProject.name + "-msw.xml" + "</value>\n</entry>\n</ini>\n")
        outfile.close()
        print(fileName + " written.")
    except OSError:
        print("Error writing " + fileName)


###################################################################################################
selectedProject = ScriptureObjects.ScriptureText(Project)
myFiles = selectedProject.files()

try:
    dirName = selectedProject.directory + "\\WordSend\\"
    os.mkdir(dirName)
    print(dirName + " created.")
except OSError:
    print("Using existing directory " + dirName)

xiniName = dirName + "joboptions.xini"
updateXini(xiniName)
print('Paratext resumes after you exit usfm2word.exe.')
os.system("usfm2word.exe " + xiniName + " /p")
#sys.stderr.write("\n\nPress <Enter> to end\n")
#sys.stdin.read(1)
